﻿//-----------------------------------------------------------------------
// <copyright file="ProjectsAndCommandsSelectorViewModel.cs" author="Artak Mkrtchyan">
//     Creative Commons - GNU General Public License (http://creativecommons.org/licenses/GPL/2.0/
// </copyright>
// <author>Artak Mkrtchyan</author>
// <email>mkArtak@gmail.com</email>
// <date>02/06/2013</date>
//-----------------------------------------------------------------------

using ConsoleHoster.Common.Utilities;
using ConsoleHoster.Common.Utilities.Threading;
using ConsoleHoster.Common.ViewModel;
using ConsoleHoster.Model;
using ConsoleHoster.Model.Entities;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;

namespace ConsoleHoster.ViewModel
{
	public class ProjectsAndCommandsSelectorViewModel : ViewModelBase
	{
		private IEnumerable<Pair<string, bool>> projects;
		private IDictionary<string, IList<Pair<string, bool>>> commands;
		private Pair<string, bool> selectedProject;
		private ProjectsFilterMode mode;

		private readonly IEnumerable<ConsoleProject> originalProjects;

		public ProjectsAndCommandsSelectorViewModel(ProjectsFilterMode argMode, IEnumerable<ConsoleProject> argProjects, IDispatcher argDispatcher, ILogger argLogger)
			: base(argDispatcher, new ComponentLogger("ProjectsAndCommandsSelectorViewModel", argLogger))
		{
			ValidationManager.RequireArgumentNotNull(argProjects, "argProjects");

			IList<Pair<string, bool>> tmpProjects = new List<Pair<string, bool>>();
			this.projects = tmpProjects;
			this.commands = new Dictionary<string, IList<Pair<string, bool>>>();

			this.originalProjects = argProjects;
			foreach (ConsoleProject tmpProject in this.originalProjects)
			{
				tmpProjects.Add(new Pair<string, bool>(tmpProject.Name, true));
				this.commands.Add(tmpProject.Name, tmpProject.Commands.Select(item => new Pair<string, bool>(item.Name, true)).ToList());
			}

			this.mode = argMode;
			this.WindowTitle = this.mode == ProjectsFilterMode.Export ? "Export projects..." : "Import projects...";
			this.SaveButtonTitle = this.mode == ProjectsFilterMode.Export ? "Export" : "Import";
		}

		public IEnumerable<ConsoleProject> GetFilteredProjectsList()
		{
			IList<ConsoleProject> tmpResult = new List<ConsoleProject>();
			foreach (string tmpProjectName in this.Projects.Where(item => item.Item2).Select(item => item.Item1))
			{
				ConsoleProject tmpOriginalProject = this.originalProjects.Where(item => item.Name == tmpProjectName).Single();
				ConsoleProject tmpProject = tmpOriginalProject.GetCopy(false);
				tmpProject.Commands = new ObservableCollection<CommandData>();
				foreach (string tmpCommandName in this.GetFilteredCommandsForProject(tmpProjectName))
				{
					tmpProject.Commands.Add(GetOriginalCommandByName(tmpOriginalProject, tmpCommandName));
				}

				tmpResult.Add(tmpProject);
			}

			return tmpResult;
		}

		private static CommandData GetOriginalCommandByName(ConsoleProject argProject, string argCommandName)
		{
			return argProject.Commands.Single(item => item.Name == argCommandName);
		}

		private IEnumerable<string> GetFilteredCommandsForProject(string tmpProjectName)
		{
			return this.commands[tmpProjectName].Where(item => item.Item2).Select(item => item.Item1);
		}

		public IEnumerable<Pair<string, bool>> Projects
		{
			get
			{
				return this.projects;
			}
		}

		public Pair<string, bool> SelectedProject
		{
			get
			{
				return this.selectedProject;
			}
			set
			{
				if (this.SetPropertyValue("SelectedProject", ref this.selectedProject, value))
				{
					this.NotifyPropertyChange("SelectedProjectCommands");
				}
			}
		}

		public IEnumerable<Pair<string, bool>> SelectedProjectCommands
		{
			get
			{
				IList<Pair<string, bool>> tmpResult;
				if (this.SelectedProject == null || !this.commands.TryGetValue(this.SelectedProject.Item1, out tmpResult))
				{
					tmpResult = null;
				}
				return tmpResult;
			}
		}

		public string SaveButtonTitle
		{
			get;
			private set;
		}

		public string WindowTitle
		{
			get;
			private set;
		}
	}
}
